#include "Clean.h"

static void FreeFilterDeviceObject(IN PDEVICE_OBJECT DeviceObject)
{
    if (!DeviceObject) return;

    PDEVICE_EXTENSION lpDeviceExtension = DeviceObject->DeviceExtension;
    IoDetachDevice(lpDeviceExtension->AttachedToDeviceObject);
    IoDeleteDevice(DeviceObject);
}

void FreeControlDeviceObject(IN PDEVICE_OBJECT DeviceObject)
{
    UNICODE_STRING usSymbolicLinkName = { 0 };

    if (DeviceObject)
        IoDeleteDevice(DeviceObject);

    RtlInitUnicodeString(&usSymbolicLinkName, USTRING_SYMBOLIC_LINK_NAME);
    IoDeleteSymbolicLink(&usSymbolicLinkName);
}

VOID DriverUnload(IN PDRIVER_OBJECT DriverObject)
{
    PDEVICE_OBJECT lpDeivceObject = DriverObject->DeviceObject;
    PDEVICE_OBJECT lpNextObject = NULL;
    NTSTATUS ntStatus;
    PKTHREAD lpCurrentThread;

    lpCurrentThread = KeGetCurrentThread();
    KeSetPriorityThread(lpCurrentThread, LOW_REALTIME_PRIORITY);

    if (KfGlobals.KbIrpRead)
    {
        InterlockedExchange64((LONG64*)(&((KfGlobals.KbDriverObject)->MajorFunction[IRP_MJ_READ])), (LONG64)KfGlobals.KbIrpRead);
        ObDereferenceObject(KfGlobals.KbDriverObject);
    }

    ntStatus = IoAcquireRemoveLock(&KfGlobals.RemoveLock, TAG_USE_REMOVE_LOCK);
    if (STATUS_SUCCESS != ntStatus) return;
    IoReleaseRemoveLockAndWait(&KfGlobals.RemoveLock, TAG_USE_REMOVE_LOCK);

    while (lpDeivceObject)
    {
        lpNextObject = lpDeivceObject->NextDevice;

        if (CONTROL == GET_DEVICETYPE_FROM_EXTENSION(lpDeivceObject))
        {
            FreeControlDeviceObject(lpDeivceObject);
        }
        else if (FILTER == GET_DEVICETYPE_FROM_EXTENSION(lpDeivceObject))
        {
            FreeFilterDeviceObject(lpDeivceObject);
        }

        lpDeivceObject = lpNextObject;
    }
}

